#include "GraphScript.h"
#include "GraphCache.h"
#include "T_BITMAP.h"
#include "clazz.h"
#include "CodingConvert.h"

static int Bitmap_release(lua_State *L){
	void *p = touserdata(L,1);
	if(p){
		delete (T_BITMAP *)p;
	}
	return 0;
}

static int Bitmap_create(lua_State *L){
	int top = lua_gettop(L);
	wchar_t *fileName = CharToWchar(luaL_checkstring(L,1));
	int col = (int)lua_tointeger(L,2);
	int row = (int)lua_tointeger(L,3);
	if(col < 1) col = 1;
	if(row < 1) row = 1;
	T_BITMAP *bmp = T_BITMAP::create(fileName,col,row);
	ModuleInstance(L,bmp,"Bitmap",false);
	top = lua_gettop(L);
	return 1;
}

static int Bitmap_getSize(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	ModuleInstance(L, new Gdiplus::SizeF(bmp->getSize()),"Size",true);
	return 1;
}

static int Bitmap_setCR(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	int c = (int)lua_tointeger(L,2);
	int r = (int)lua_tointeger(L,3);
	bmp->setCR(c,r);
	return 0;
}

static int Bitmap_getCols(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	lua_pushinteger(L,bmp->getCols());
	return 1;
}

static int Bitmap_getRows(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	lua_pushinteger(L,bmp->getRows());
	return 1;
}

static int Bitmap_getPoint(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	Gdiplus::PointF *pnt = (Gdiplus::PointF *)ModuleCheck(L,2,"Point");
	POINT *xy = new POINT();
	*xy = bmp->getPoint(*pnt);
	ModuleInstance(L,xy,"POINT",true);
	return 1;
}

static int Bitmap_getIndex(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	Gdiplus::PointF *pnt = (Gdiplus::PointF *)ModuleCheck(L,2,"Point");
	lua_pushinteger(L,bmp->getIndex(*pnt));
	return 1;
}

static int Bitmap_getCellSize(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	Gdiplus::SizeF *sz = new Gdiplus::SizeF(bmp->getCellSize());
	ModuleInstance(L,&sz,"Size",true);
	return 1;
}

static int Bitmap_getBounds(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	if(lua_isnumber(L,2)){
		Gdiplus::RectF *ret = new Gdiplus::RectF(bmp->getBounds((int)lua_tointeger(L,2)));
		ModuleInstance(L,ret,"Rect",true);
		return 1;
	}
	POINT *pnt = (POINT *)ModuleCheck(L,2,"POINT");
	Gdiplus::RectF *ret = new Gdiplus::RectF(bmp->getBounds(*pnt));
	ModuleInstance(L,ret,"Rect",true);
	return 1;
}

static int Bitmap_isValid(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	lua_pushboolean(L,bmp->isValid());
	return 1;
}

static int Bitmap_getFilePath(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	char * filePath = WcharToChar(bmp->getFilePath());
	lua_pushstring(L,filePath);
	return 1;
}

static int Bitmap_tostring(lua_State *L){
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,1,"Bitmap");
	char * filePath = WcharToChar(bmp->getFilePath());
	lua_pushfstring(L,"Bitmap:%s:0x%p",filePath,lua_touserdata(L,1));
	return 1;
}

static int GCache_getInstance(lua_State *L){
	GraphCache *instance = GraphCache::getInstance();
	if(!instance){
		return 0;
	}
	ModuleInstance(L,instance,"GraphCache");
	return 1;
}

static int GCache_create(lua_State *L){
	GraphCache *instance = GraphCache::create();
	ModuleInstance(L,instance,"GraphCache");
	return 1;
}

static int GCache_release(lua_State *L){
	GraphCache::release();
	return 0;
}

static int GCache_add(lua_State *L){
	GraphCache *instance = (GraphCache *)ModuleCheck(L,1,"GraphCache");
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,3,"Bitmap");
	if(lua_isnumber(L,2)){
		lua_pushboolean(L,instance->add((int)luaL_checkinteger(L,2),bmp));
	}else{
		const char *str = luaL_checkstring(L,2);
		lua_pushboolean(L,instance->add(str,bmp));
	}
	return 1;
}

static int GCache_get(lua_State *L){
	GraphCache *instance = (GraphCache *)ModuleCheck(L,1,"GraphCache");
	T_BITMAP *bmp = 0;
	if(lua_isnumber(L,2)){
		bmp = instance->get((int)luaL_checkinteger(L,2));
	}else{
		bmp = instance->get(luaL_checkstring(L,2));
	}
	if(!bmp){
		lua_pushnil(L);
	}else{
		ModuleInstance(L,bmp,"Bitmap",false);
	}
	return 1;
}

static int GCache_replace(lua_State *L){
	GraphCache *instance = (GraphCache *)ModuleCheck(L,1,"GraphCache");
	T_BITMAP *bmp = (T_BITMAP *)ModuleCheck(L,3,"Bitmap");
	lua_pushboolean(L,instance->replace(luaL_checkstring(L,2),bmp));
	return 1;
}

static int GCache_remove(lua_State *L){
	GraphCache *instance = (GraphCache *)ModuleCheck(L,1,"GraphCache");
	lua_pushboolean(L,instance->remove(luaL_checkstring(L,2)));
	return 1;
}

static int GCache_getSize(lua_State *L){
	GraphCache *instance = (GraphCache *)ModuleCheck(L,1,"GraphCache");
	lua_pushinteger(L,instance->getSize());
	return 1;
}

static int GCache_tostring(lua_State *L){
	GraphCache *instance = (GraphCache *)ModuleCheck(L,1,"GraphCache");
	lua_pushfstring(L,"GraphCache:(size = %d):0x%p",instance->getSize(),lua_touserdata(L,1));
	return 1;
}

int lua_opengraph(lua_State *L){
	BeginModule(L,"Bitmap");
	InitModule(L,0,Bitmap_release);
	StaticFunction(L,"create",Bitmap_create);
	NormalFunction(L,"getSize",Bitmap_getSize);
	NormalFunction(L,"setCR",Bitmap_setCR);
	NormalFunction(L,"getCols",Bitmap_getCols);
	NormalFunction(L,"getRows",Bitmap_getRows);
	NormalFunction(L,"getPoint",Bitmap_getPoint);
	NormalFunction(L,"getIndex",Bitmap_getIndex);
	NormalFunction(L,"getCellSize",Bitmap_getCellSize);
	NormalFunction(L,"getBounds",Bitmap_getBounds);
	NormalFunction(L,"isValid",Bitmap_isValid);
	NormalFunction(L,"getFilePath",Bitmap_getFilePath);
	ModuleToString(L,Bitmap_tostring);
	EndModule(L);

	BeginModule(L,"GraphCache");
	InitModule(L,0,0);
	StaticFunction(L,"getInstance",GCache_getInstance);
	StaticFunction(L,"create",GCache_create);
	StaticFunction(L,"release",GCache_release);
	NormalFunction(L,"add",GCache_add);
	NormalFunction(L,"get",GCache_get);
	NormalFunction(L,"replace",GCache_replace);
	NormalFunction(L,"remove",GCache_remove);
	NormalFunction(L,"getSize",GCache_getSize);
	ModuleToString(L,GCache_tostring);
	EndModule(L);
	return 1;
}


int lua_closegraph(lua_State *L){
	lua_pushnil(L);
	lua_setglobal(L,"Bitmap");
	lua_pushnil(L);
	lua_setglobal(L,"GraphCache");
	return 0;
}